home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 182_01 / sb_217.c < prev    next >
Text File  |  1990-07-30  |  14KB  |  639 lines

  1. #define VERSION "sb 2.17 07-02-85"
  2. #define PUBDIR "/usr/spool/uucppublic"
  3.  
  4. /*% cc -O -DUSG sb.c -o sb
  5.  
  6.  * sb.c By Chuck Forsberg
  7.  *
  8.  * A small program for Unix which can send 1 or more
  9.  * files in Batch mode to computers running YAM. (Use "rb" in YAM.)
  10.  * Supports the CRC option or regular checksum.
  11.  * Exit status is 0 for all transfers completed successfully,
  12.  * 1 for 1 or more unreadable files or'd with 200 for incomplete file xfer.
  13.  *
  14.  * accepts -k option for 1kb record length.
  15.  *
  16.  * sb is derived from yam2.c
  17.  * Uses buffered i/o to reduce the CPU time compared to UMODEM.
  18.  *  USG UNIX (3.0) ioctl conventions courtesy  Jeff Martin
  19.  *     cc -O -DV7  sb.c -o sb        vanilla Unix version 7
  20.  *    cc -O -DUSG sb.c -o sb        USG (3.0) Unix
  21.  *  ******* Some systems (Venix, Coherent, Regulus) do not *******
  22.  *  ******* support tty raw mode read(2) identically to    *******
  23.  *  ******* Unix. ONEREAD must be defined to force one     *******
  24.  *  ******* character reads for these systems.           *******
  25.  */
  26.  
  27. #define LOGFILE "/tmp/sblog"
  28.  
  29. #include <stdio.h>
  30. #include <signal.h>
  31. #include <setjmp.h>
  32. #include <ctype.h>
  33.  
  34. #define PATHLEN 256
  35. #define OK 0
  36. #define FALSE 0
  37. #define TRUE 1
  38. #define ERROR (-1)
  39.  
  40. #define HOWMANY 2
  41. #include "rbsb.c"    /* most of the system dependent stuff here */
  42.  
  43. FILE *in;
  44.  
  45. /* Ward Christensen / CP/M parameters - Don't change these! */
  46. #define ENQ 005
  47. #define CAN ('X'&037)
  48. #define XOFF ('s'&037)
  49. #define XON ('q'&037)
  50. #define SOH 1
  51. #define STX 2
  52. #define EOT 4
  53. #define ACK 6
  54. #define NAK 025
  55. #define CPMEOF 032
  56. #define WANTCRC 0103    /* send C not NAK to get crc not checksum */
  57. #define WANTG 0107    /* Send G not NAK to get nonstop batch xmsn */
  58. #define TIMEOUT (-2)
  59. #define ERRORMAX 5
  60. #define RETRYMAX 5
  61. #define SECSIZ 128    /* cp/m's Magic Number record size */
  62. #define KSIZE 1024
  63.  
  64. char Lastrx;
  65. char Crcflg;
  66. int Wcsmask=0377;
  67. int Verbose=0;
  68. int Restricted=0;    /* restricted; no /.. or ../ in filenames */
  69. int Quiet=0;        /* overrides logic that would otherwise set verbose */
  70. int Fullname=0;        /* transmit full pathname */
  71. int Unlinkafter=0;    /* Unlink file after it is sent */
  72. int Dottoslash=0;    /* Change foo.bar.baz to foo/bar/baz */
  73. int firstsec;
  74. int errcnt=0;        /* number of files unreadable */
  75. int blklen=SECSIZ;    /* length of transmitted records */
  76. int Optiong;        /* Let it rip no wait for sector ACK's */
  77. int Noeofseen;
  78. int Totsecs;        /* total number of sectors this file */
  79. char txbuf[KSIZE];
  80. int Filcnt=0;        /* count of number of files opened */
  81.  
  82. jmp_buf tohere;        /* For the interrupt on RX timeout */
  83.  
  84. unsigned updcrc();
  85. char *substr(), *getenv();
  86.  
  87. /* called by signal interrupt or terminate to clean things up */
  88. bibi(n)
  89. {
  90.     canit(); fflush(stdout); mode(0);
  91.     fprintf(stderr, "sb: caught signal %d; exiting\n", n);
  92.     if (n == SIGQUIT)
  93.         abort();
  94.     exit(128+n);
  95. }
  96.  
  97. #ifdef REGULUS
  98. sendline(c)
  99. {
  100.     static char d[2];
  101.  
  102.     d[0] = c&Wcsmask;
  103.     write(1, d, 1);
  104. }
  105. #else
  106. #define sendline(c) putchar(c & Wcsmask)
  107. #endif
  108.  
  109. main(argc, argv)
  110. char *argv[];
  111. {
  112.     register char *cp;
  113.     register npats;
  114.     int agcnt; char **agcv;
  115.     char **patts;
  116.     int exitcode;
  117. #ifndef REGULUS
  118.     static char xXbuf[BUFSIZ];
  119. #endif
  120.  
  121.     if ((cp=getenv("SHELL")) && substr(cp, "rsh"))
  122.         Restricted=TRUE;
  123.  
  124.     npats=0;
  125.     if (argc<2)
  126.         goto usage;
  127. #ifndef REGULUS
  128.     setbuf(stdout, xXbuf);        
  129. #endif
  130.     while (--argc) {
  131.         cp = *++argv;
  132.         if (*cp == '-') {
  133.             while ( *++cp) {
  134.                 switch(*cp) {
  135.                 case '1':
  136.                     iofd = 1; break;
  137.                 case '7':
  138.                     Wcsmask=0177; break;
  139.                 case 'd':
  140.                     ++Dottoslash;
  141.                     /* **** FALL THROUGH TO **** */
  142.                 case 'f':
  143.                     Fullname=TRUE; break;
  144.                 case 'k':
  145.                     blklen=KSIZE; break;
  146.                 case 'q':
  147.                     Quiet=TRUE; Verbose=0; break;
  148.                 case 'u':
  149.                     ++Unlinkafter; break;
  150.                 case 'v':
  151.                     ++Verbose; break;
  152.                 default:
  153.                     goto usage;
  154.                 }
  155.             }
  156.         }
  157.         else if ( !npats && argc>0) {
  158.             if (argv[0][0]) {
  159.                 npats=argc;
  160.                 patts=argv;
  161.             }
  162.         }
  163.     }
  164.     if (npats < 1) {
  165. usage:
  166.         fprintf(stderr,"%s by Chuck Forsberg\n", VERSION);
  167.         fprintf(stderr,"Usage: sb [-7dfkquv] file ...\n");
  168.         exit(1);
  169.     }
  170.     
  171.     if (Verbose) {
  172.         if (freopen(LOGFILE, "a", stderr)==NULL) {
  173.             printf("Can't open log file %s\n",LOGFILE);
  174.             exit(0200);
  175.         }
  176.         setbuf(stderr, NULL);
  177.     }
  178.     if (fromcu() && !Quiet) {
  179.         if (Verbose == 0)
  180.             Verbose = 2;
  181.     }
  182.     if (Verbose != 1) {
  183.         fprintf(stderr, "sb: %d file%s requested:\r\n",
  184.          npats, npats>1?"s":"");
  185.         for ( agcnt=npats, agcv=patts; --agcnt>=0; ) {
  186.             fprintf(stderr, "%s ", *agcv++);
  187.         }
  188.     }
  189.  
  190.     mode(1);
  191.     if (signal(SIGINT, bibi) == SIG_IGN) {
  192.         signal(SIGINT, SIG_IGN); signal(SIGKILL, SIG_IGN);
  193.     }
  194.     else {
  195.         signal(SIGINT, bibi); signal(SIGKILL, bibi);
  196.         signal(SIGQUIT, bibi);
  197.     }
  198.  
  199.     if (wcsend(npats, patts)==ERROR) {
  200.         exitcode=0200;
  201.         canit();
  202.     }
  203.     fflush(stdout);
  204.     mode(0);
  205.     exit((errcnt != 0) | exitcode);
  206. }
  207.  
  208. wcsend(argc, argp)
  209. char *argp[];
  210. {
  211.     register n;
  212.  
  213.     Crcflg=FALSE;
  214.     firstsec=TRUE;
  215.     for (n=0; n<argc; ++n) {
  216.         Totsecs = 0;
  217.         if (wcs(argp[n])==ERROR)
  218.             goto fubar;
  219.     }
  220.     Totsecs = 0;
  221.     if (Filcnt==0) {    /* bitch if we couldn't open ANY files */
  222.         fprintf(stderr,"\r\nCan't open any requested files.\n");
  223.         return ERROR;
  224.     }
  225.     else if (wctxpn("")==ERROR)
  226.         goto fubar;
  227.     return OK;
  228. fubar:
  229.     canit(); return ERROR;
  230. }
  231.  
  232. wcs(oname)
  233. char *oname;
  234. {
  235.     register c;
  236.     register char *p;
  237.     struct stat f;
  238.     char name[PATHLEN];
  239.  
  240.     strcpy(name, oname);
  241.  
  242.     if (Restricted) {
  243.         /* restrict pathnames to current tree or uucppublic */
  244.         if ( substr(name, "../")
  245.          || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) ) {
  246.             canit();
  247.             fprintf(stderr,"\r\nsb:\tSecurity Violation\r\n");
  248.             return ERROR;
  249.         }
  250.     }
  251.  
  252.     if ((in=fopen(oname, "r"))==NULL) {
  253.         ++errcnt;
  254.         return OK;    /* pass over it, there may be others */
  255.     }
  256.     ++Noeofseen;
  257.     /* Check for directory or block special files */
  258. #ifndef REGULUS        /* This doesn't seem to work on Regulus */
  259.     fstat(fileno(in), &f);
  260.     c = f.st_mode & S_IFMT;
  261.     if (c == S_IFDIR || c == S_IFBLK) {
  262.         fclose(in);
  263.         return OK;
  264.     }
  265. #endif
  266.     ++Filcnt;
  267.     if (wctxpn(name)== ERROR)
  268.         return ERROR;
  269.     if (wctx()==ERROR)
  270.         return ERROR;
  271.     if (Unlinkafter)
  272.         unlink(oname);
  273.     return 0;
  274. }
  275.  
  276. /*
  277.  * generate and transmit pathname block consisting of
  278.  *  pathname (null terminated),
  279.  *  file length, mode time and file mode in octal
  280.  *  as provided by the Unix fstat call.
  281.  *  N.B.: modifies the passed name, may extend it!
  282.  */
  283. wctxpn(name)
  284. char *name;
  285. {
  286.     register firstch;
  287.     register char *p, *q;
  288.     char name2[PATHLEN];
  289.     struct stat f;
  290.  
  291.     logent("\r\nAwaiting pathname nak for %s\r\n", *name?name:"<END>");
  292.     if (getnak())
  293.         return ERROR;
  294.  
  295.     q = (char *) 0;
  296.     if (Dottoslash) {        /* change . to . */
  297.         for (p=name; *p; ++p) {
  298.             if (*p == '/')
  299.                 q = p;
  300.             else if (*p == '.')
  301.                 *(q=p) = '/';
  302.         }
  303.         if (q && strlen(++q) > 8) {    /* If name>8 chars */
  304.             q += 8;            /*   make it .ext */
  305.             strcpy(name2, q);    /* save excess of name */
  306.             *q = '.';
  307.             strcpy(++q, name2);    /* add it back */
  308.         }
  309.     }
  310.  
  311.     for (p=name, q=txbuf ; *p; )
  312.         if ((*q++ = *p++) == '/' && !Fullname)
  313.             q = txbuf;
  314.     *q++ = 0;
  315.     p=q;
  316.     while (q < (txbuf + KSIZE))
  317.         *q++ = 0;
  318. #ifndef REGULUS        /* This doesn't seem to work on Regulus */
  319.     if (*name && fstat(fileno(in), &f)!= -1)
  320.         sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
  321. #endif
  322.     /* force 1k blocks if name won't fit in 128 byte block */
  323.     if (strlen(txbuf) > 127)
  324.         blklen=KSIZE;
  325.     if (wcputsec(txbuf, 0, SECSIZ)==ERROR)
  326.         return ERROR;
  327.     return OK;
  328. }
  329.  
  330. getnak()
  331. {
  332.     register firstch;
  333.  
  334.     Lastrx = 0;
  335.     for (;;) {
  336.         switch (firstch = readock(800,2)) {
  337.         case TIMEOUT:
  338.             logent("Timeout on pathname\n");
  339.             return TRUE;
  340.         case WANTG:
  341.             mode(2);    /* Set cbreak, XON/XOFF, etc. */
  342.             Optiong = TRUE;
  343.         case WANTCRC:
  344.             Crcflg = TRUE;
  345.         case NAK:
  346.             return FALSE;
  347.         case CAN:
  348.             if (Lastrx == CAN)
  349.                 return TRUE;
  350.         default:
  351.             break;
  352.         }
  353.         Lastrx = firstch;
  354.     }
  355. }
  356.  
  357.  
  358. wctx()
  359. {
  360.     register int sectnum, attempts, firstch;
  361.  
  362.     firstsec=TRUE;
  363.  
  364.     while ((firstch=readock(400, 2))!=NAK && firstch != WANTCRC
  365.       && firstch!=TIMEOUT